using System.Collections;
using ScriptableObject;
using UnityEngine;
using UnityEngine.InputSystem;

namespace Player
{
    public class PlayerController : MonoBehaviour
    {
        #region 移动参数
        [Header("移动参数")] 
        [SerializeField] private float moveSpeed = 5f;
        #endregion

        #region 跳跃参数
        [Header("跳跃参数")]
        [SerializeField] private float jumpForce = 8f;
        [SerializeField] private float fallMultiplier = 2.5f;
        [SerializeField] private float lowJumpMultiplier = 2f;
        [SerializeField] private int maxJumpCount = 2;
        [SerializeField] private int jumpCount;
        [SerializeField] public bool isJumpPressed;
        [SerializeField] private bool canJump = true;
        [SerializeField] private bool isJumpHeld;
        #endregion

        #region 冲刺参数
        [Header("冲刺参数")]
        [SerializeField] private float dashSpeed = 15f;
        [SerializeField] private float dashDuration = 0.2f;
        [SerializeField] private float dashCooldown = 1f;
        public bool isDashing;
        private bool canDash = true;
        private bool hasDashedInAir;
        #endregion

        #region 受伤参数
        [Header("受伤参数")] 
        public bool isHurt;
        public float hurtForce;
        public bool isDead;
        #endregion

        #region 飞盘配置
        [Header("飞盘配置")]
        public GameObject boomerangPrefab;
        [Tooltip("飞盘生成基准偏移量")]
        [SerializeField] private float boomerangOffset = 0.7f;
        [SerializeField] private float throwCooldown = 1f;
        public Transform generatePosition;
        [Tooltip("墙体检测层级")]
        [SerializeField] private LayerMask wallCheckLayers;
        private bool canThrow = true;
        #endregion

        #region 事件监听
        [Header("事件监听")]
        public SceneLoadEventSO loadEvent;
        public VoidEventSO afterSceneLoadedEvent;
        #endregion

        #region 组件引用
        private Rigidbody2D rb;
        private PlayerInputControl inputControl;
        private PhysicsCheck physicsCheck;
        private new CapsuleCollider2D collider;
        #endregion

        #region 生命周期管理
        private void Awake()
        {
            audioSource = GetComponent<AudioSource>();
            rb = GetComponent<Rigidbody2D>();
            physicsCheck = GetComponent<PhysicsCheck>();
            collider = GetComponent<CapsuleCollider2D>();
            inputControl = new PlayerInputControl();
        }

        private void Start()
        {
            PlayerData playerData = SaveManager.Instance.LoadPlayerData();            
            transform.position = playerData.Position;
            
        }

        private void OnEnable()
        {
            inputControl.Enable();
            inputControl.Gameplay.Jump.started += OnJumpStarted;
            inputControl.Gameplay.Jump.canceled += OnJumpCanceled;
            inputControl.Gameplay.Dash.started += OnDashStarted;
            inputControl.Gameplay.Throw.performed += OnThrowPerformed;
            
            loadEvent.LoadRequestEvent += OnLoadEvent;
            afterSceneLoadedEvent.OnEventRaised += OnAfterSceneLoadedEvent;
        }

        private void OnDisable()
        {
            inputControl.Disable();
            inputControl.Gameplay.Jump.started -= OnJumpStarted;
            inputControl.Gameplay.Jump.canceled -= OnJumpCanceled;
            inputControl.Gameplay.Dash.started -= OnDashStarted;
            inputControl.Gameplay.Throw.performed -= OnThrowPerformed;
            
            loadEvent.LoadRequestEvent -= OnLoadEvent;
            afterSceneLoadedEvent.OnEventRaised -= OnAfterSceneLoadedEvent;
        }

        private void Update()
        {
            if (!isDashing && !isHurt)
            {
                HandleJumpCountReset();
            }
        }

        private void FixedUpdate()
        {
            if (!isDashing && !isHurt)
            {
                HandleMovement();
                HandleJump();
                BetterJumpPhysics();
            }
        }
        #endregion

        #region 输入处理
        private void OnJumpStarted(InputAction.CallbackContext context)
        {
            if (CanJump())
            {
                isJumpPressed = true;
                isJumpHeld = true;
            }
        }

        private void OnJumpCanceled(InputAction.CallbackContext context) => isJumpHeld = false;

        private void OnDashStarted(InputAction.CallbackContext context)
        {
            if (canDash) StartCoroutine(PerformDash());
        }

        private void OnThrowPerformed(InputAction.CallbackContext context)
        {
            if (canThrow)
            {
                StartCoroutine(ThrowBoomerang());
            }
        }
        #endregion

        #region 核心逻辑    
        //修改
        public AudioClip jumpClip,
            RunClip;
        AudioSource audioSource;
        public static bool canMove = true;
        private void HandleMovement()
        {
            Vector2 input = inputControl.Gameplay.Move.ReadValue<Vector2>();

            if (!IsWallBlocking(input.x))
            {
                if(canMove)
                {
                    audioSource.volume = 1;
                    audioSource.Play();
                    rb.velocity = new(input.x * moveSpeed, rb.velocity.y);
                    HandleCharacterFlip(input.x);
                }
                else if (physicsCheck.IsGrounded)
                {
                    canMove = true;
                }                
            }            
            
        }

        private void HandleJump()
        {
            if (!isJumpPressed) return;
            
            rb.velocity += new Vector2(0, jumpForce);
            audioSource.volume = 0.3f;
            audioSource.PlayOneShot(jumpClip);
            jumpCount--;
            isJumpPressed = false;
            StartCoroutine(JumpCooldown());
        }

        private IEnumerator PerformDash()
        {
            if (!physicsCheck.IsGrounded && hasDashedInAir) yield break;

            canDash = false;
            isDashing = true;

            Vector2 dashDirection = GetDashDirection();
            float originalGravity = rb.gravityScale;

            rb.gravityScale = 0;
            rb.velocity = dashDirection * dashSpeed;

            yield return new WaitForSeconds(dashDuration);

            rb.gravityScale = originalGravity;
            isDashing = false;

            if (!physicsCheck.IsGrounded) hasDashedInAir = true;
            yield return new WaitForSeconds(dashCooldown);
            canDash = true;
        }

        private void BetterJumpPhysics()
        {
            if (rb.velocity.y < 0)
            {
                rb.velocity += Vector2.up * (Physics2D.gravity.y * (fallMultiplier - 1) * Time.fixedDeltaTime);
            }
            else if (rb.velocity.y > 0 && !isJumpHeld)
            {
                rb.velocity += Vector2.up * (Physics2D.gravity.y * (lowJumpMultiplier - 1) * Time.fixedDeltaTime);
            }
        }
        #endregion

        #region 飞盘逻辑
        private IEnumerator ThrowBoomerang()
        {
            canThrow = false;

            Vector2 spawnDir = GetSpawnDirection();
            //Vector2 spawnPos = CalculateSafeSpawnPosition(spawnDir);
            Vector2 spawnPos = generatePosition.position;
            InstantiateBoomerang(spawnPos, spawnDir);

            yield return new WaitForSeconds(throwCooldown);
            canThrow = true;
        }

        private Vector2 GetSpawnDirection() => 
            new Vector2(Mathf.Sign(transform.localScale.x), 0);

        private Vector2 CalculateSafeSpawnPosition(Vector2 direction)
        {
            float checkDistance = boomerangOffset + 0.1f;
            RaycastHit2D hit = Physics2D.BoxCast(
                collider.bounds.center,
                collider.size * 0.8f,
                0f,
                direction,
                checkDistance,
                wallCheckLayers);

            float actualOffset = hit.collider ? 
                Mathf.Max(hit.distance - 0.1f, 0.05f) : 
                boomerangOffset;

            return (Vector2)transform.position + 
                   direction * actualOffset + 
                   Vector2.up * 0.3f;
        }

        private void InstantiateBoomerang(Vector2 position, Vector2 direction)
        {
            GameObject instance = Instantiate(boomerangPrefab, position, Quaternion.identity);
            if (instance.TryGetComponent(out Boomerang boomerang))
            {
                boomerang.Initialize(direction);
            }
        }
        #endregion

        #region 辅助方法
        private void HandleJumpCountReset()
        {
            if (physicsCheck.IsGrounded)
            {                
                jumpCount = maxJumpCount;                
                hasDashedInAir = false;
            }
        }

        private bool IsWallBlocking(float horizontalInput)
        {
            return Mathf.Abs(horizontalInput) > 0.1f && 
                   physicsCheck.IsOnWall && 
                   Mathf.Approximately(Mathf.Sign(horizontalInput), Mathf.Sign(transform.localScale.x));
        }

        private void HandleCharacterFlip(float inputX)
        {
            if (Mathf.Abs(inputX) > 0.1f)
            {
                transform.localScale = new Vector3(Mathf.Sign(inputX), 1, 1);
            }
        }

        private IEnumerator JumpCooldown()
        {
            canJump = false;
            yield return new WaitForSeconds(1f);
            canJump = true;
        }

        private bool CanJump() => 
            jumpCount > 0 && canJump;
        
        private Vector2 GetDashDirection()
        {
            Vector2 input = inputControl.Gameplay.Move.ReadValue<Vector2>();
            return input != Vector2.zero ? 
                input.normalized : 
                new Vector2(transform.localScale.x > 0 ? 1 : -1, 0);
        }
        #endregion

        #region 事件处理
        private void OnAfterSceneLoadedEvent() => inputControl.Gameplay.Enable();
        private void OnLoadEvent(GameSceneSO arg0, Vector3 arg1, bool arg2) => inputControl.Gameplay.Disable();
        #endregion

        #region 受伤处理
        public void GetHurt(Transform attacker)
        {
            isHurt = true;
            rb.velocity = Vector2.zero;
            Vector2 dir = new Vector2((transform.position.x - attacker.position.x), 0).normalized;
            rb.AddForce(dir * hurtForce, ForceMode2D.Impulse);
            StartCoroutine(ResetHurtState(0.5f));
        }

        private IEnumerator ResetHurtState(float delay)
        {
            yield return new WaitForSeconds(delay);
            isHurt = false;
        }

        public void PlayerDead()
        {
            isDead = true;
            inputControl.Gameplay.Disable();
        }
        #endregion

        #region 调试辅助
        private void OnDrawGizmosSelected()
        {
            if (collider == null) return;
            
            Gizmos.color = Color.yellow;
            Vector2 direction = new Vector2(Mathf.Sign(transform.localScale.x), 0);
            Vector2 origin = collider.bounds.center;
            
            Gizmos.DrawWireCube(origin + direction * (boomerangOffset * 0.5f + 0.1f),
                collider.size * 0.8f);
        }
        #endregion
    }
}